<?php

namespace app\common\business\sendFcm;

use app\common\business\BaseBus;
use app\common\model\SendLog;
use app\common\model\SendMsg;
use app\common\model\UserFcmToken;
use support\Log;

class FcmMessage extends BaseBus
{
    protected static $jsonFilePath;
    protected static $userFcmToken;
    protected static $projectId;
    public function __construct()
    {
        self::$projectId = 'calm-segment-416609';
        self::$jsonFilePath = base_path().'/calm-segment-416609-56b780217794.json';
        self::$userFcmToken = new UserFcmToken();
    }

    /**
     * 推送消息
     * @param $user
     * @param $sendMsg
     * @param $type
     * @return false|int|mixed|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function fcmSend($user,$sendMsg=[],$type=0)
    {
        $AccessToken = self::getFirebaseAccessToken();
        // 查询最新的消息
        if (empty($sendMsg)) {
            $sendMsg = SendMsg::field('id,title,content')
                ->order(['id'=>'desc'])->find();
        }
        $title = $sendMsg['title'] ?? '你有一条新消息';
        $body = $sendMsg['content'] ?? '你有一条新消息';
        $projectId = self::$projectId;
        $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";
        $ttlSeconds = 86400;
        $message = [
            'message' => [
                'token' => $user['fcm_token'],
                'notification' => [
                    'title' => $title,
                    'body' => $body
                ],
//                'data' => ['k'=>'v'],
                // Android 平台的离线消息设置
                'android' => [
                    'ttl' => $ttlSeconds . 's',           // 离线保留时间
                    'priority' => 'high',                 // 消息优先级 (在android级别)
                    'notification' => [
                        'channel_id' => 'default',        // 通知渠道
                        'sound' => 'default',             // 声音
                        'default_sound' => true,          // 默认声音
                        'default_vibrate_timings' => true, // 默认震动
                        'default_light_settings' => true   // 默认灯光
                    ]
                ],
                // iOS 平台的离线消息设置
                'apns' => [
                    'headers' => [
                        'apns-expiration' => (string)(time() + $ttlSeconds), // 过期时间戳
                        'apns-priority' => '10' // 高优先级
                    ],
                    'payload' => [
                        'aps' => [
                            'alert' => [
                                'title' => $title,
                                'body' => $body
                            ],
                            'sound' => 'default',
                            'badge' => 1
                        ]
                    ]
                ]
            ]
        ];

//        if ($type == 1) {
//            $message['message']['data'] = ['init' => 'initFcm'];
//        }

        $headers = [
            'Authorization: Bearer ' . $AccessToken,
            'Content-Type: application/json; UTF-8'
        ];

        $result = self::getCurl($url,$message,$headers);

        $sendLogData = [
            'msg_id' => $sendMsg['id'],
            'user_ids' => $user['id'],
            'created_at' => time()
        ];

        $hasLog = SendLog::field('id,user_ids')->where(['msg_id' => $sendMsg['id'], 'type' => 0])
            ->order(['id'=>'desc'])->find();
        if (isset($result['name']) && !empty($result['name'])) {
            if (empty($hasLog)) {
                $logId = (new SendLog)->insertGetId($sendLogData);
            } else {
                $saveData = [
                    'user_ids' => $hasLog['user_ids'].','.$user['id'],
                    'updated_at' => time()
                ];
                SendLog::where(['id'=>$hasLog['id']])->update($saveData);
                $logId = $hasLog['id'];
            }
            return $logId;
        } else {
            if (!empty($hasLog)) {
                $sendLogData['updated_at'] = time();
                $sendLogData['error_msg'] = json_encode($result, JSON_UNESCAPED_UNICODE);
                SendLog::where(['id' => $hasLog['id']])->update($sendLogData);
            }
            \support\Log::error('发送消息失败-error:'.json_encode($result, JSON_UNESCAPED_UNICODE));
        }
        return false;
    }
    // 获取授权token
    public static function getFirebaseAccessToken() {
        $client = new \Google_Client();
        $client->setAuthConfig(self::$jsonFilePath);
        $client->addScope('https://www.googleapis.com/auth/firebase.messaging');
        $tokenData = $client->fetchAccessTokenWithAssertion();
        if (isset($tokenData['access_token'])) {
            return $tokenData['access_token'];
        }
        self::errorBus('获取访问令牌失败' . json_encode($tokenData));
    }

    /**
     * 使用 Dry Run 模式验证一个 FCM Token 是否有效
     * @param string $accessToken FCM 访问令牌
     * @param string $fcmTokenToValidate 要验证的设备 Token
     * @return array 包含验证结果和原因的数组
     */
    public static function validateFcmToken($accessToken, $fcmTokenToValidate) {
        if (!$accessToken) {
            return ['isValid' => false, 'reason' => '无效的访问令牌，无法继续验证。'];
        }

        // 项目ID
        $projectId = self::$projectId;
        $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";

        $message = [
            'message' => [
                'token' => $fcmTokenToValidate
            ],
            'validate_only' => true // 关键：开启 Dry Run 模式
        ];

        $headers = [
            'Authorization: Bearer ' . $accessToken,
            'Content-Type: application/json; UTF-8'
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));
        $responseBody = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $responseData = json_decode($responseBody, true);

        if ($httpCode === 200) {
            // HTTP 200 不代表 Token 有效，必须检查 body 中是否有 error
            if (isset($responseData['error'])) {
                // 典型错误：用户已卸载App
                $errorMessage = $responseData['error']['message'] ?? 'Unknown error.';
                return ['isValid' => false, 'reason' => "Token 无效 (FCM 报告错误: {$errorMessage})"];
            }
            return ['isValid' => true, 'reason' => 'Token 有效'];
        } elseif ($httpCode === 400) {
            return ['isValid' => false, 'reason' => 'Token 格式错误 (HTTP 400 Bad Request)'];
        } elseif ($httpCode === 401 || $httpCode === 403) {
            return ['isValid' => false, 'reason' => '认证失败 (请检查你的服务帐号或访问令牌)'];
        } else {
            return ['isValid' => false, 'reason' => "发生未知错误 (HTTP Code: {$httpCode})"];
        }
    }

    /**
     * 更新firebase用户设备token
     * @param $userId
     * @param $fcmToken
     * @param $expTime
     * @return bool
     */
    public static function setFcmToken($userId, $fcmToken, $expTime, $deviceId, $deviceModel, $platform='')
    {
        $where = [
            'fcm_token' => $fcmToken,
            'device_id' => $deviceId,
            'device_model' => $deviceModel
        ];
        $userToken = self::$userFcmToken->getFindData($where);
        $expTime = $expTime / 1000;
        try {
            if (empty($userToken)) {
                $tokenId = self::$userFcmToken->insertGetId([
                    'user_id' => $userId,
                    'fcm_token' => $fcmToken,
                    'exp_time' => $expTime,
                    'device_id' => $deviceId,
                    'device_model' => $deviceModel,
                    'created_at' => time()
                ]);
            } else {
                $userToken->user_id = $userId;
                $userToken->fcm_token = $fcmToken;
                $userToken->exp_time = $expTime;
                if (empty($userToken['device_id'])) {
                    $userToken->device_id = $deviceId;
                }
                if (empty($userToken['device_model'])) {
                    $userToken->device_model = $deviceModel;
                }
                $userToken->updated_at = time();
                $userToken->save();

                $tokenId = $userToken['id'];
            }
        } catch (\Exception $e) {
            Log::error('setFcmToken-error:'.$e->getMessage().$e->getFile().$e->getLine());
            return false;
        }
        // 订阅主题
        $fcmTopicBus = new \app\common\business\sendFcm\FcmTopic();
        $fcmTopicBus::subscribeToTopic($fcmToken);
        if (!empty($platform)) {
            // 初始化发送消息
            self::fcmSend(['id' => $tokenId, 'fcm_token' => $fcmToken], [], 1);
        }
        return true;
    }
}
